/* Copyright © 2010 LPRM
Universidade Federal do Espírito Santo - RNP-GT CWTools

This file is part of JoinUs!.

JoinUs! is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

JoinUs! is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JoinUs!. If not, see <http://www.gnu.org/licenses/>. */
package android.isisufes.services;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Service;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.isisufes.util.Crypter;
import android.isisufes.util.DBHelper;
import android.isisufes.util.ServerCom;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.Log;


public class FileManagerDaemon extends Service {
	static private SQLiteDatabase db;
	private DBHelper dbh;
	private getterLoop gl;
	private Cursor c; //TODO: Não está sendo setado nunca.
	
	static public void queueDownload(Map<String, String> m) {
		String sql = "INSERT INTO fileInfo (idattach,userid,campaigncreator,size,campaignname,filename,status,type, hash, desc) VALUES ('"
			+ m.get("idattach") + "','" + ServerCom.id + "','" + m.get("campCreator") + "','" + m.get("size") + "','" + m.get("campName") + "','" + m.get("filename") + "', 'Queued' ,'" + m.get("type") + "','" + m.get("hash") + "','" + m.get("desc") + "');";
		db.execSQL(sql);
	}

	public void onCreate() {
		super.onCreate();

		dbh = new DBHelper();
		db = this.openOrCreateDatabase("homedb", MODE_PRIVATE, null);
		dbh.onCreate(db);
		gl = new getterLoop();
	}

	protected void onStart(int startId, Bundle b) {
		Intent intent = new Intent();
		intent.putExtras(b);
		super.onStart(intent, startId);
		new Thread(gl).start();
	}

	private class getterLoop implements Runnable {
		public boolean done = false;
		private Downloader du;
		public void run() {
			ContentValues cv = new ContentValues();
			int id, pos;
			while (!done) {
				//uri = cr.query("fileInfo", null, "status = 'Queued' AND userid = '" + ServerCom.id + "'", null, null, null, null);
				if (c != null) {
					for (int i = 0; i < c.getCount(); ++i) {
						c.moveToPosition(i);
						//cr.update(get, values, where, selectionArgs)
						//c.updateString(6, "Downloading");
						//c.commitUpdates();
						pos = c.getColumnIndex("_id");
						id = c.getInt(pos);
						cv.put("filename", "Downloading");
						db.update("fileInfo", cv, "_id = " + id, null);
						
						du = new Downloader(c.getString(0), c.getString(8));
						new Thread(du).start();
					}
				}
				SystemClock.sleep(10000); 
			}
		}
	}

	public static String uploadFile(Map<String, String> m, String content) {                         
		String targetURL = "http://" + ServerCom.host + ":" + ServerCom.port + "/JoinUs-ApplicationServer/servlets/Upload";
		Log.d("UPLOADER", "************** Uploading " + m.get("filename") + " to " + targetURL);

		String msg = null;
		try {
			msg = Crypter.encrypt(ServerCom.key, m);
		} catch (Exception e) {
			Log.d("UPLOADER", e.toString());
			return "ENCRIPTION_ERROR";
		}

		ArrayList<NameValuePair> parameters = new ArrayList<NameValuePair>();
		parameters.add(new BasicNameValuePair("msg", msg));
		parameters.add(new BasicNameValuePair("id", ServerCom.id));
		parameters.add(new BasicNameValuePair("file", content));

		HttpPost pm = new HttpPost(targetURL);
		UrlEncodedFormEntity ent = null;
		try {
			ent = new UrlEncodedFormEntity(parameters);
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
			return "ERRO NO UPLOAD DE ARQUIVO";
		}
		pm.setEntity(ent);
		
		HttpClient client = new DefaultHttpClient();

		HttpResponse response;
		try {
			response = client.execute(pm);
		} catch (IOException e) {
			Log.d("UPLOADER", e.toString());
			return "HTTP_ERROR";
		}
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
			Log.d("UPLOADER", "************ Upload complete, response=" + "asasasa");
		} else {
			Log.d("UPLOADER", "********************** Upload failed, response=" + response.getStatusLine().getReasonPhrase()); 	//Log.d("UPLOADER", "********************** Upload failed, response=" + HttpStatus.getStatusText(status));
		}

		return "OK";
	}

	private class Downloader implements Runnable {
		private String url, idattach, hash;

		public Downloader(String ia, String h) {
			hash = h;
			idattach = ia;
			url = "GET /JoinUs-ApplicationServer/files/" + hash + "\n";
		}

		private boolean isDownloading() {
			boolean boolReturn;
			Cursor c = db.query("fileInfo", null, "idattach = '" + idattach + "' AND userid = '" + ServerCom.id + "' AND status = 'Downloading'", null, null, null, null);
			c.moveToPosition(0);  // c.moveTo(0);
			boolReturn = (c.getString(6).compareTo("Downloading") == 0);
			c.close();

			return boolReturn;
		}

		public void run() { 
			String r = downloadFile(idattach);
			Log.d("DOWNLOADER", r);
		}

		public String downloadFile(String idattach) {
			Socket ps;
			BufferedReader br;
			BufferedWriter pw;
			boolean df = false;

			try {
				ps = new Socket(ServerCom.host, ServerCom.port);
				pw = new BufferedWriter(new OutputStreamWriter(ps.getOutputStream()), 8192);
				br = new BufferedReader(new InputStreamReader(ps.getInputStream()), 8192);
				pw.append(url);
				pw.append("Host: " + ServerCom.host + ":" + ServerCom.port + "\n\n");
				pw.flush();
			} catch (Exception e) {
				Log.d("ERRODOWNLOAD", e.toString());
				return "SERVER_ERROR";
			}

			String s = null;
			StringBuilder fc = new StringBuilder();

			try {
				while ((s = br.readLine()) != null && (df = isDownloading()))
					fc.append(s);
			} catch (IOException e1) {
				Log.d("ERRODOWNLOAD", e1.toString());
				try {
					ps.close();
				} catch (Exception e2) {
					Log.d("ERROCLOSING", e2.toString());
				}

				db.execSQL("UPDATE fileInfo SET status = 'Canceled' WHERE idattach = '" + idattach + "' AND userid='" + ServerCom.id + "'");
				return "DOWNLOAD_ERROR";
			}

			db.execSQL("UPDATE fileInfo SET status = '" + (df ? "Complete'" : "Canceled'") + " WHERE idattach = '" + idattach + "' AND userid='" + ServerCom.id + "'");
			if (df)
				db.execSQL("INSERT INTO fileContent (idattach, id, content) VALUES ('" + idattach + "','" + ServerCom.id + "','" + fc.toString() + "');");

			try {
				ps.close();
			} catch (IOException e) {
				Log.d("ERROCLOSING", e.toString());
				return "SOCKET_ERROR";
			}

			return "OK";
		}
	}

	public IBinder onBind(Intent arg0) { return null; }

	public void onDestroy() {
		super.onDestroy();
		gl.done = true;
		db.close();
	}
}
